package com.lp.batch.service.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.XmlMappingException;
import org.springframework.oxm.castor.CastorMarshaller;
import org.springframework.stereotype.Service;
import org.springframework.xml.xpath.Jaxp13XPathTemplate;
import org.springframework.xml.xpath.XPathException;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import com.lp.batch.domain.Taxonomies;
import com.lp.batch.service.TaxonomyService;

/**
 * A class that unmarshall content of an XML file to Java objects using Castor
 * 
 * @author Zainul Franciscus
 * 
 */
@Service("taxonomyService")
public class TaxonomyServiceImpl implements TaxonomyService {

	/**
	 * Used to unmarshall taxonomies object from an XML file.
	 */
	@Autowired
	private CastorMarshaller castorMarshaller;

	/**
	 * Used to retrieve history in a destination.xml file.
	 */
	@Autowired
	private Jaxp13XPathTemplate xpath;

	/*
	 * select a history of a node from a destination.xml file
	 * 
	 * @see com.lp.batch.service.impl.TaxonomyService#selectHistory(int,
	 * java.lang.String)
	 */
	public String selectHistory(int nodeId, String xmlfile) throws IOException {

		Node node = xpath.evaluateAsNode("/destinations/destination[@atlas_id=" + nodeId + "]/history/history/history", createSAXSource(xmlfile));
		if (node != null) {
			return StringUtils.trim(node.getTextContent());
		} else {

			return "";
		}
	}

	/*
	 * select an introduction of a node from a destionation.xml file
	 * 
	 * @see com.lp.batch.service.TaxonomyService#selectIntroduction(int,
	 * java.lang.String)
	 */
	public String selectIntroduction(int nodeId, String xmlfile) throws XPathException, FileNotFoundException {

		Node node = xpath.evaluateAsNode("/destinations/destination[@atlas_id=" + nodeId + "]/introductory/introduction/overview", createSAXSource(xmlfile));
		if (node != null) {
			return StringUtils.trim(node.getTextContent());
		} else {

			return "";
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.lp.batch.service.TaxonomyService#selectIntroAndHistory(int,
	 * java.lang.String)
	 */
	public String selectIntroAndHistory(int nodeId, String xmlfile) throws IOException {
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(selectHistory(nodeId, xmlfile));
		stringBuilder.append(selectIntroduction(nodeId, xmlfile));
		return stringBuilder.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.lp.batch.service.impl.TaxonomyService#selectTaxonomies(java.lang.
	 * String)
	 */
	public Taxonomies selectTaxonomies(String xmlfile) throws XmlMappingException, FileNotFoundException, IOException {

		return (Taxonomies) castorMarshaller.unmarshal(createSAXSource(xmlfile));

	}

	/**
	 * @param xmlfile
	 * @return a SAXSource that can be used to unmarshal an XML file using a SAX
	 *         Parser.
	 * @throws FileNotFoundException
	 */
	private SAXSource createSAXSource(String xmlfile) throws FileNotFoundException {
		FileInputStream is = new FileInputStream(xmlfile);
		SAXSource saxSource = new SAXSource(new InputSource(is));

		return saxSource;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.lp.batch.service.impl.TaxonomyService#writeToXML(com.lp.batch.domain
	 * .Taxonomies, java.lang.String)
	 */
	public void writeToXML(Taxonomies taxonomies, String filepath) throws XmlMappingException, IOException {
		FileOutputStream os = null;
		try {
			os = new FileOutputStream(filepath);
			castorMarshaller.marshal(taxonomies, new StreamResult(os));
		} finally {
			if (os != null) {
				os.close();
			}
		}
	}

}
